package logic

import (
	"common/global"
	"common/model"
	"context"
	"fmt"
	"gorm.io/gorm"
	"time"
	"user_server/proto"
)

// SignIn 处理用户签到请求
func (s *UserServer) SignIn(ctx context.Context, req *user.SignInRequest) (*user.SignInResponse, error) {
	userId := req.UserId
	currentTime := time.Now()
	currentDate := currentTime.Format("2006-01-02")
	yearMonth := currentTime.Format("200601")
	day := currentTime.Day() - 1 // Bitmap从0开始计数
	if userId <= 0 {
		return nil, fmt.Errorf("无效的用户ID")
	}
	//检查用户今天是否已经签到，如果已签到则返回相应信息。
	redisKey := fmt.Sprintf("user:sign:%d:%s", userId, yearMonth)
	isSigned, err := global.Client.GetBit(ctx, redisKey, int64(day)).Result()
	if err != nil {
		return nil, fmt.Errorf("签到检查失败: %v", err)
	}
	if isSigned == 1 {
		return &user.SignInResponse{Success: false, Message: "今日已签到", ContinuousDays: 0}, nil
	}

	//开启数据库事务，并设置事务回滚的异常处理。
	tx := global.Db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	//查询用户当前状态，如果用户不存在则回滚事务并返回错误。
	var o model.User
	if err := tx.Where("id = ?", userId).First(&o).Error; err != nil {
		tx.Rollback()
		return nil, fmt.Errorf("用户不存在: %v", err)
	}

	//计算用户的连续签到天数。
	newContinuous := 1
	if o.LastSignDate != "" {
		lastDate, err := time.Parse(time.RFC3339, o.LastSignDate)
		if err != nil {
			tx.Rollback()
			return nil, fmt.Errorf("解析上次签到日期失败: %v", err)
		}
		if lastDate.AddDate(0, 0, 1).Format("2006-01-02") == currentDate {
			newContinuous = o.ContinuousSignDays + 1
		}
	}

	//更新Redis中的签到记录，如果更新失败则回滚事务并返回错误。
	if _, err := global.Client.SetBit(ctx, redisKey, int64(day), 1).Result(); err != nil {
		tx.Rollback()
		return nil, fmt.Errorf("签到记录失败: %v", err)
	}

	//更新用户数据库中的签到信息，如果更新失败则回滚事务并返回错误。
	if err := o.UpdateSignInfo(newContinuous, currentDate); err != nil {
		tx.Rollback()
		return nil, fmt.Errorf("更新签到信息失败: %v", err)
	}

	awardCards := 0
	switch newContinuous {
	case 3:
		awardCards = 1
	case 7:
		awardCards = 2
	case 15:
		awardCards = 3
	case 30:
		awardCards = 5
	}

	if awardCards > 0 {
		if err := tx.Model(&o).Update("retroactive_cards", gorm.Expr("retroactive_cards + ?", awardCards)).Error; err != nil {
			tx.Rollback()
			return nil, fmt.Errorf("奖励补签卡失败: %v", err)
		}
	}

	// 新增签到记录
	signRecord := model.SignRecord{
		UserId:        userId,
		SignDate:      currentTime,
		Type:          1,
		IsRetroactive: 0, // 普通签到，非补签
	}
	if err := tx.Create(&signRecord).Error; err != nil {
		tx.Rollback()
		return nil, fmt.Errorf("创建签到记录失败: %v", err)
	}

	//提交事务，如果提交失败则返回错误。
	if err := tx.Commit().Error; err != nil {
		return nil, fmt.Errorf("事务提交失败: %v", err)
	}

	//返回签到成功的响应信息。
	return &user.SignInResponse{
		Success:        true,
		Message:        "签到成功",
		ContinuousDays: int32(newContinuous),
	}, nil
}
